package org.dromara.hm.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; // 导入Slf4j
import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.hm.domain.HmCustomer;
import org.dromara.hm.domain.HmCustomerTransferHistory;
import org.dromara.hm.domain.HmThresholdManagement;
import org.dromara.hm.domain.HmTodoItems;
import org.dromara.hm.domain.bo.HmTodoItemsBo;
import org.dromara.hm.domain.vo.saleOrder.HmSaleOrderVo;
import org.dromara.hm.mapper.HmCustomerMapper;
import org.dromara.hm.mapper.HmProductMapper;
import org.dromara.hm.mapper.saleOrder.HmSaleOrderMapper;
import org.dromara.hm.mapper.HmStockMapper;
import org.dromara.hm.mapper.HmThresholdManagementMapper;
import org.dromara.hm.mapper.HmTodoItemsMapper;
import org.dromara.hm.mapper.StatisticsMapper;
import org.dromara.hm.service.IHmCustomerService; // 导入 IHmCustomerService
import org.dromara.hm.service.IHmProductService; // 导入 IHmProductService
import org.dromara.hm.service.IHmTodoItemsService;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.mapper.SysUserRoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; // 导入 Transactional

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 定时任务实现Service
 *
 * @Author If404 Hzy
 * @Date 2025-2025/4/7-16:11
 * @Version 1.0
 */
@RequiredArgsConstructor
@Service
@Slf4j // 添加Slf4j注解
public class ProductUseJobService
{
    private final HmSaleOrderMapper baseMapper;

    private final HmProductMapper productMapper; // 保持对旧Mapper的引用，但后续会通过Service调用

    private final IHmProductService hmProductService; // 注入新的产品Service

    private final HmCustomerMapper customerMapper;

    private final HmTodoItemsMapper todoItemsMapper;

    private final StatisticsMapper statisticsMapper;

    private final IHmTodoItemsService todoItemsService;

    private final HmSaleOrderServiceImpl saleOrderService;

    private final IHmCustomerService hmCustomerService; // 注入 IHmCustomerService

    @Autowired
    private HmThresholdManagementMapper hmThresholdManagementMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private HmStockMapper hmStockMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    private final HmThresholdManagementMapper thresholdManagementMapper;

    /**
     * @author opensnail
     * 产品使⽤阈值提醒定时任务
     */
    // 每日凌晨2点执行，根据实际业务需求调整
    @Scheduled(cron = "0 0 2 * * ?")
    public void productExecuteReminder()
    {
        productExecute();
        log.info("定时任务执行时间: {}", new java.util.Date()); // 使用日志输出
    }

    /**
     * @author opensnail
     * 员工入职提醒定时任务
     */
    // @Scheduled(cron = "0 0 4 * * ?") // 每日凌晨4点执行
    public void userExecuteReminder()
    {
        userExecute();
        log.info("员工入职提醒定时任务执行时间: {}", new java.util.Date());
    }

    /**
     * @author opensnail
     * 客户生日提醒定时任务
     */
    // 每日凌晨1点执行
    @Scheduled(cron = "0 0 1 * * ?")
    public void customerExecuteReminder()
    {
        customerExecute();
        log.info("客户生日提醒定时任务执行时间: {}", new java.util.Date());
    }

    /**
     * @author opensnail
     * 客户是否设置为公海（公池）定时任务
     */
    // 每日凌晨1点30分执行，确保在客户生日提醒之后
    @Scheduled(cron = "0 30 1 * * ?")
    public void customerHighSeasReminder()
    {
        customerHighSeas();
        log.info("客户公海（公池）提醒定时任务执行时间: {}", new java.util.Date());
    }

    /**
     * @author opensnail
     * 订单回访待办任务
     */
    // 每日凌晨1点执行
    @Scheduled(cron = "0 0 1 * * *")
    public void orderReturnVisitToDoTaskReminder()
    {
        insertProductHmSaleOrderBo();
        log.info("订单回访待办任务执行时间: {}", new java.util.Date());
    }

    /**
     * @author opensnail
     * 产品使⽤阈值提醒定时任务
     */
    public void productExecute()
    {
        List<HmThresholdManagement> thresholds = selectThresholdManagement("PRODUCT-USAGE");
        if (thresholds.size() < 2) {
            log.warn("产品使用阈值配置不足，请检查hm_threshold_management表中PRODUCT-USAGE类型的配置。");
            return;
        }
        HmThresholdManagement threshold = thresholds.get(0);
        HmThresholdManagement threshold2 = thresholds.get(1);

        //第一次阈值添加代办任务
        productFirstExecute(threshold, threshold2);
        //第二次阈值添加代办任务
        productTwoExecute(threshold, threshold2);

    }

    //第一次阈值添加代办任务
    public void productFirstExecute(HmThresholdManagement threshold, HmThresholdManagement threshold2)
    {
        //  产生一条待办事项,事项的类型阈值提醒,待办事项的接收人为店员

        int remainingDays = Integer.parseInt(threshold.getRemainingDays());//日期差值
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -remainingDays);
        Date targetDate = calendar.getTime();
        // 将 Date 转换为 LocalDate
        LocalDate targetLocalDate = targetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 构建查询条件
        List<HmSaleOrderVo> list = statisticsMapper.selectVoList(targetLocalDate);
        for (HmSaleOrderVo item : list)
        {
            // 检查是否已经存在该订单的阈值提醒待办，避免重复创建
            if (!isTodoItemExist(item.getSaleId(), "3", item.getSaleUser(), remainingDays)) {
                HmTodoItemsBo hmTodoItemsBo = new HmTodoItemsBo();
                hmTodoItemsBo.setOrderId(item.getSaleId());
                hmTodoItemsBo.setTodoType("3"); // 回访提醒阈值提醒
                hmTodoItemsBo.setStatus("0"); // 状态
                hmTodoItemsBo.setCreateType("1"); // 系统生成
                hmTodoItemsBo.setCreateDept(item.getSaleDept()); // 创建部门id
                hmTodoItemsBo.setTodoDesc("产品阈值提醒:" + item.getCustomerName() + "购买产品" + item.getSaleProductName() + "达使⽤阈值,预计还有" + threshold.getRemainingDays() + "天使⽤完毕,请及时联系通知,");
                hmTodoItemsBo.setTodoPersonId(item.getSaleUser());
                hmTodoItemsBo.setTodoPersonName(item.getSaleUserName());

                // 设置提交人信息（系统生成，使用系统用户）
                hmTodoItemsBo.setSubmitterId(1L);
                hmTodoItemsBo.setSubmitterName("系统");

                // 设置审核人信息（待办人即审核人）
                hmTodoItemsBo.setApproverId(item.getSaleUser());
                hmTodoItemsBo.setApproverName(item.getSaleUserName());

                //todo 添加第二阈值的相关信息
                Map<String, String> user = statisticsMapper.selectManager(item.getCreateDept());
                // 确保 user 不为 null 且包含 key
                if (ObjectUtil.isNotEmpty(user) && user.containsKey("user_id")) {
                    hmTodoItemsBo.setTodoTwoPersonId(Long.valueOf(user.get("user_id")));
                    hmTodoItemsBo.setTodoTwoPersonName(user.get("nick_name"));
                } else {
                    log.warn("未找到部门:{}的店长信息，无法设置第二阈值提醒人。", item.getCreateDept());
                    hmTodoItemsBo.setTodoTwoPersonId(null); // 或者设置为默认管理员ID
                    hmTodoItemsBo.setTodoTwoPersonName(null); // 或者设置为默认管理员名称
                }

                Calendar calendar2 = Calendar.getInstance();
                calendar2.add(Calendar.DAY_OF_YEAR, Integer.parseInt(threshold2.getRemainingDays()) - Integer.parseInt(threshold.getRemainingDays()));// 增加 10 天
                hmTodoItemsBo.setUseTimeTwo(calendar2.getTime());
                todoItemsService.insertByBo(hmTodoItemsBo);
            }
        }

    }

    //第二次阈值添加代办任务
    public void productTwoExecute(HmThresholdManagement threshold, HmThresholdManagement threshold2)
    {
        //  产生一条待办事项,事项的类型阈值提醒,待办事项的接收人为店长

        int remainingDays = Integer.parseInt(threshold2.getRemainingDays());//日期差值
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -remainingDays);
        Date targetDate = calendar.getTime();
        // 将 Date 转换为 LocalDate
        LocalDate targetLocalDate = targetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 构建查询条件 类型为3（阈值提醒），状态为未办结的（"0"）
        QueryWrapper<HmTodoItems> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("todo_type", "3");
        queryWrapper.eq("status", "0");
        queryWrapper.apply("DATE(use_time_two) = {0}", targetLocalDate);//只计算年月日
        // 执行查询
        List<HmTodoItems> list = DataPermissionHelper.ignore(() ->
        {
            return todoItemsMapper.selectList(queryWrapper);
        });
        for (HmTodoItems item : list)
        {
            // 检查是否已经存在该订单的第二阈值提醒待办，避免重复创建
            if (!isTodoItemExist(item.getOrderId(), "3", item.getTodoTwoPersonId(), remainingDays)) {
                // 创建新的待办，而不是直接修改旧的todoId
                HmTodoItems newItem = new HmTodoItems();
                // 复制相关属性
                newItem.setOrderId(item.getOrderId());
                newItem.setTodoType("3"); // 阈值提醒
                newItem.setStatus("0"); // 未完成
                newItem.setCreateType("1"); // 系统生成
                newItem.setCreateDept(item.getCreateDept()); // 创建部门id
                String todoDesc = item.getTodoDesc();
                // 替换描述中的天数信息
                newItem.setTodoDesc(todoDesc.replace(threshold.getRemainingDays() + "天", threshold2.getRemainingDays() + "天"));
                newItem.setTodoPersonId(item.getTodoTwoPersonId());
                newItem.setTodoPersonName(item.getTodoTwoPersonName());

                // 设置提交人信息（系统生成，使用系统用户）
                newItem.setSubmitterId(1L);
                newItem.setSubmitterName("系统");

                // 设置审核人信息（待办人即审核人）
                newItem.setApproverId(item.getTodoTwoPersonId());
                newItem.setApproverName(item.getTodoTwoPersonName());

                newItem.setUseTimeTwo(item.getUseTimeTwo()); // 保留第二阈值时间
                newItem.setFollowCustomerId(item.getFollowCustomerId());
                newItem.setFollowCustomerName(item.getFollowCustomerName());
                newItem.setThresholdDays(remainingDays); // 更新阈值天数

                todoItemsMapper.insert(newItem);
            }
        }
    }

    /**
     * 检查是否存在重复的待办事项
     * @param orderId 订单ID
     * @param todoType 待办类型
     * @param todoPersonId 待办人ID
     * @param thresholdDays 阈值天数
     * @return 如果存在，返回true；否则返回false
     */
    private boolean isTodoItemExist(Long orderId, String todoType, Long todoPersonId, Integer thresholdDays) {
        QueryWrapper<HmTodoItems> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("todo_type", todoType)
            .eq("todo_person_id", todoPersonId)
            .eq("status", "0"); // 未完成状态

        if (orderId != null) {
            queryWrapper.eq("order_id", orderId);
        }
        if (thresholdDays != null) {
            queryWrapper.eq("threshold_days", thresholdDays);
        }
        return todoItemsMapper.selectCount(queryWrapper) > 0;
    }


    /**
     * @author opensnail
     * 员工入职提醒定时任务
     */
    public void userExecute()
    {
        List<HmThresholdManagement> thresholds = selectThresholdManagement("STAFF");
        if (ObjectUtil.isEmpty(thresholds)) {
            log.warn("员工入职阈值配置不存在，请检查hm_threshold_management表中STAFF类型的配置。");
            return;
        }
        //  产生一条待办事项,事项的类型阈值提醒,待办事项的接收人默认为人事角色
        // 先查询 sysUserRole 表中 roleId 为指定值的所有 userIds
        // TODO: 建议将角色ID定义为常量或从配置中读取，避免硬编码
        QueryWrapper<SysUserRole> roleWrapper = new QueryWrapper<>();
        roleWrapper.eq("role_id", "1869282280335163393"); // 人事角色ID
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(roleWrapper);
        if (ObjectUtil.isNotEmpty(sysUserRoles)){
            // 根据提取的 userId 查询 sysuser 表中的用户信息
            // 假设人事角色只有一个用户或者只通知第一个用户
            SysUser hrUser = sysUserMapper.selectById(sysUserRoles.get(0).getUserId());
            if (ObjectUtil.isNull(hrUser)) {
                log.error("未找到人事角色对应的用户，无法发送员工入职提醒。");
                return;
            }
            String hrUserName = hrUser.getNickName(); // 使用昵称
            Long hrUserId = hrUser.getUserId();

            for (HmThresholdManagement threshold : thresholds)
            {
                int totalDay = Integer.parseInt(threshold.getMessage()); // 假设message存储总天数
                int remainingDays = totalDay - Integer.parseInt(threshold.getRemainingDays());//日期差值
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, -remainingDays);
                Date targetDate = calendar.getTime();
                // 将 Date 转换为 LocalDate
                LocalDate targetLocalDate = targetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                // 构建查询条件
                QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
                queryWrapper.apply("DATE(entry_date) = {0}", targetLocalDate);//只计算年月日
                // 执行查询
                List<SysUser> allUsers = sysUserMapper.selectList(queryWrapper);
                for (SysUser user : allUsers)
                {
                    // 检查是否已经存在该员工的入职提醒待办
                    if (!isTodoItemExist(null, "3", hrUserId, remainingDays)) { // 入职提醒也用阈值提醒类型"3"
                        HmTodoItemsBo hmTodoItemsBo = new HmTodoItemsBo();
                        hmTodoItemsBo.setTodoType("3"); // 阈值提醒
                        hmTodoItemsBo.setStatus("0"); // 状态
                        hmTodoItemsBo.setCreateType("1"); // 系统生成
                        hmTodoItemsBo.setTodoDesc(String.format("员工入职提醒：员工[%s]入职满[%s]天", user.getNickName(), threshold.getRemainingDays()));
                        hmTodoItemsBo.setTodoPersonId(hrUserId);
                        hmTodoItemsBo.setTodoPersonName(hrUserName);

                        // 设置提交人信息（系统生成，使用系统用户）
                        hmTodoItemsBo.setSubmitterId(1L);
                        hmTodoItemsBo.setSubmitterName("系统");

                        // 设置审核人信息（待办人即审核人）
                        hmTodoItemsBo.setApproverId(hrUserId);
                        hmTodoItemsBo.setApproverName(hrUserName);

                        hmTodoItemsBo.setThresholdDays(remainingDays); // 记录阈值天数
                        todoItemsService.insertByBo(hmTodoItemsBo);
                    }
                }
            }
        }

    }

    public List<HmThresholdManagement> selectThresholdManagement(String type)
    {
        QueryWrapper<HmThresholdManagement> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("threshold_code", type).orderByAsc("sort"); // 按 sort 字段正序排序
        return hmThresholdManagementMapper.selectList(queryWrapper);
    }

    /**
     * @author opensnail
     * 客户生日、结婚纪念日提醒定时任务
     */
    public void customerExecute()
    {
        List<HmThresholdManagement> thresholdBirth = selectThresholdManagement("CUSTOMER-BIRTHDAY");
        List<HmThresholdManagement> thresholdMarry = selectThresholdManagement("CUSTOMER-MEMORIAL");

        if (ObjectUtil.isEmpty(thresholdBirth) && ObjectUtil.isEmpty(thresholdMarry)) {
            log.warn("客户生日/纪念日阈值配置不存在，请检查hm_threshold_management表中CUSTOMER-BIRTHDAY或CUSTOMER-MEMORIAL类型的配置。");
            return;
        }

        //  产生一条待办事项,事项的类型阈值提醒,待办事项的接收人为对应的服务⼈员
        for (HmThresholdManagement threshold : thresholdBirth)
        {
            int remainingDays = Integer.parseInt(threshold.getRemainingDays());//日期差值
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_YEAR, -remainingDays);
            Date targetDate = calendar.getTime();
            // 将 Date 转换为 LocalDate
            LocalDate targetLocalDate = targetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            // 定义日期格式  todo 前端定义日期格式也应为MM/dd
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
            // 将LocalDate格式化为指定格式的字符串
            String formattedDate = targetLocalDate.format(formatter);
            QueryWrapper<HmCustomer> queryWrapper = new QueryWrapper<>();
            // 根据生日字段计算 与当前时间匹配阈值数据的客户，生成代办事项
            queryWrapper.isNotNull("customer_birthday");
            queryWrapper.isNotNull("staff_id"); // 必须有服务人员
            queryWrapper.eq("is_public", false); // 只处理非公池客户
            queryWrapper.likeLeft("customer_birthday", formattedDate);//只匹配月日
            List<HmCustomer> hmCustomers = DataPermissionHelper.ignore(() ->
            {
                return customerMapper.selectList(queryWrapper);
            });
            insertCustomerHmSaleOrderBo(hmCustomers, remainingDays, "1");
        }
        for (HmThresholdManagement threshold : thresholdMarry)
        {
            int remainingDays = Integer.parseInt(threshold.getRemainingDays());//日期差值
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_YEAR, -remainingDays);
            Date targetDate = calendar.getTime();
            // 将 Date 转换为 LocalDate
            LocalDate targetLocalDate = targetDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            // 定义日期格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
            // 将LocalDate格式化为指定格式的字符串
            String formattedDate = targetLocalDate.format(formatter);
            QueryWrapper<HmCustomer> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNotNull("wedding_day");
            queryWrapper.isNotNull("staff_id"); // 必须有服务人员
            queryWrapper.eq("is_public", false); // 只处理非公池客户
            // 根据生日字段计算 与当前时间匹配阈值数据的客户，生成代办事项
            queryWrapper.likeLeft("wedding_day", formattedDate);
            ;//只匹配月日
            List<HmCustomer> hmCustomers = DataPermissionHelper.ignore(() ->
            {
                return customerMapper.selectList(queryWrapper);
            });
            insertCustomerHmSaleOrderBo(hmCustomers, remainingDays, "2");
        }
    }

    /**
     * 客户生日、结婚纪念日阈值⽣成待办任务
     */
    private void insertCustomerHmSaleOrderBo(List<HmCustomer> hmCustomers, Integer remainingDays, String type)
    {
        for (HmCustomer hmCustomer : hmCustomers)
        {
            // 检查是否已经存在该客户的生日/纪念日提醒待办
            if (!isTodoItemExist(null, "2", hmCustomer.getStaffId(), remainingDays)) { // 节日祝福提醒类型"2"
                HmTodoItemsBo hmTodoItemsBo = new HmTodoItemsBo();
                hmTodoItemsBo.setTodoType("2"); // 节日祝福提醒
                hmTodoItemsBo.setStatus("0"); // 状态
                hmTodoItemsBo.setCreateType("1"); // 系统生成
                if ("1".equals(type))
                {
                    hmTodoItemsBo.setTodoDesc(String.format("客户生日提醒: 客户[%s]，距离生日还有[%s]天", hmCustomer.getCustomerName(), remainingDays));
                }
                if ("2".equals(type))
                {
                    hmTodoItemsBo.setTodoDesc(String.format("客户结婚纪念日提醒: 客户[%s]，距离结婚纪念日还有[%s]天", hmCustomer.getCustomerName(), remainingDays));
                }
                hmTodoItemsBo.setTodoPersonId(hmCustomer.getStaffId());
                hmTodoItemsBo.setTodoPersonName(hmCustomer.getStaffName());

                // 设置提交人信息（系统生成，使用系统用户）
                hmTodoItemsBo.setSubmitterId(1L);
                hmTodoItemsBo.setSubmitterName("系统");

                // 设置审核人信息（待办人即审核人）
                hmTodoItemsBo.setApproverId(hmCustomer.getStaffId());
                hmTodoItemsBo.setApproverName(hmCustomer.getStaffName());

                hmTodoItemsBo.setTodoStockDept(hmCustomer.getStoreId()); // 关联店铺
                hmTodoItemsBo.setFollowCustomerId(hmCustomer.getCustomerId()); // 关联客户ID
                hmTodoItemsBo.setFollowCustomerName(hmCustomer.getCustomerName()); // 关联客户名称
                hmTodoItemsBo.setThresholdDays(remainingDays); // 记录阈值天数
                todoItemsService.insertByBo(hmTodoItemsBo);
            }
        }
    }

    /**
     * 产品阈值⽣成待办任务
     */
    public void insertProductHmSaleOrderBo() {
        try {
            List<HmThresholdManagement> thresholds = selectThresholdManagement("SALE-ORDER-RETURN");
            if (ObjectUtil.isEmpty(thresholds)) {
                log.warn("销售订单回访提醒阈值信息不存在，请检查hm_threshold_management表中SALE-ORDER-RETURN类型的配置。");
                return;
            }
            String collect = Optional.ofNullable(thresholds)
                .orElseThrow(() -> new RuntimeException("销售订单回访提醒阈值信息不存在")).stream()
                .map(HmThresholdManagement::getRemainingDays).collect(Collectors.joining(","));
            String[] split = collect.split(",");

            for (String dayStr : split) { // 遍历每个阈值天数
                int days = Integer.parseInt(dayStr.trim());
                // 仅处理日期部分
                LocalDate triggerLocalDate = LocalDate.now().minusDays(days);

                // 查询满足条件的订单（使用时间在触发日期，且未生成指定阈值天数的待办）
                List<HmSaleOrderVo> orders = baseMapper.selectOrdersAfterDateWithNoTodo(
                    triggerLocalDate,
                    days
                );

                // 生成待办事项
                for (HmSaleOrderVo order : orders) {
                    // 再次检查是否已经存在相同阈值天数的待办，防止并发或逻辑问题导致重复
                    if (!isTodoItemExist(order.getSaleId(), "0", order.getSaleUser(), days)) { // 回访提醒类型"0"
                        HmTodoItemsBo hmTodoItemsBo = new HmTodoItemsBo();
                        hmTodoItemsBo.setOrderId(order.getSaleId());
                        hmTodoItemsBo.setTodoType("0"); // 回访提醒
                        hmTodoItemsBo.setStatus("0"); // 未完成
                        hmTodoItemsBo.setCreateType("1"); // 系统生成
                        hmTodoItemsBo.setTodoDesc(String.format(
                            "销售订单[%s],%d天回访提醒（客户：%s，产品：%s）",
                            order.getSaleId(),
                            days,
                            order.getCustomerName(),
                            order.getSaleProductName()
                        ));
                        hmTodoItemsBo.setFollowCustomerId(order.getCustomerId());
                        hmTodoItemsBo.setThresholdDays(days); // 记录阈值天数
                        hmTodoItemsBo.setFollowCustomerName(order.getCustomerName());
                        hmTodoItemsBo.setTodoPersonId(order.getSaleUser());
                        hmTodoItemsBo.setTodoPersonName(order.getSaleUserName());

                        // 设置提交人信息（系统生成，使用系统用户）
                        hmTodoItemsBo.setSubmitterId(1L);
                        hmTodoItemsBo.setSubmitterName("系统");

                        // 设置审核人信息（待办人即审核人）
                        hmTodoItemsBo.setApproverId(order.getSaleUser());
                        hmTodoItemsBo.setApproverName(order.getSaleUserName());

                        todoItemsService.insertByBo(hmTodoItemsBo);
                    }
                }
            }
        } catch (Exception e) {
            log.error("插入产品销售订单回访待办任务失败", e); // 使用日志输出错误
            //throw e; // 继续抛出异常，让上层处理
        }
    }

    /**
     * 客户公海（公池）处理逻辑
     */
    @Transactional(rollbackFor = Exception.class)
    public void customerHighSeas()
    {
        log.info("开始执行客户公海（公池）处理任务...");
        // 1. 获取公池转换阈值 (例如 90 天)
        List<HmThresholdManagement> gcThresholds = selectThresholdManagement("CUSTOMER-PUBLIC-POOL");
        if (ObjectUtil.isEmpty(gcThresholds) || gcThresholds.get(0).getRemainingDays() == null) {
            log.warn("客户公池转换阈值未配置或配置不正确，请检查hm_threshold_management表中CUSTOMER-PUBLIC-POOL类型的配置。");
            return;
        }
        int daysThreshold = Integer.parseInt(gcThresholds.get(0).getRemainingDays());

        // 2. 查询符合条件的客户列表 (非公池客户，且最近一次订单时间或最近一次回访完成时间超过指定天数)
        // 使用 @DataPermissionHelper.ignore 确保定时任务可以查询所有客户数据
        List<HmCustomer> customersToTransfer = DataPermissionHelper.ignore(() ->
            customerMapper.selectCustomersForPublicPoolTransfer(daysThreshold)
        );

        if (ObjectUtil.isEmpty(customersToTransfer)) {
            log.info("没有需要转入公池的客户。");
            return;
        }

        log.info("发现 {} 个客户需要转入公池。", customersToTransfer.size());

        // 3. 批量更新客户状态并记录转移历史
        for (HmCustomer customer : customersToTransfer) {
            try {
                // 创建一个用于更新客户的BO
                HmCustomer hmCustomerUpdate = new HmCustomer();
                hmCustomerUpdate.setCustomerId(customer.getCustomerId());
                hmCustomerUpdate.setIsPublic(true); // 设置为公池客户
                hmCustomerUpdate.setStaffId(null); // 清空服务人员
                hmCustomerUpdate.setStaffName(null); // 清空服务人员名称
                hmCustomerUpdate.setUpdateTime(new Date()); // 更新时间
                // 设置 updateBy 为系统用户或特定用户，例如 admin
                hmCustomerUpdate.setUpdateBy(1L); // 或使用一个专门的系统用户ID

                // 更新客户信息
                customerMapper.updateById(hmCustomerUpdate);

                // 记录客户转移历史
                HmCustomerTransferHistory history = new HmCustomerTransferHistory();
                history.setCustomerId(customer.getCustomerId());
                history.setCustomerName(customer.getCustomerName());
                history.setOldStaffId(customer.getStaffId());
                history.setOldStaffName(customer.getStaffName());
                history.setOldStoreId(customer.getStoreId());
                history.setOldStoreName(customer.getStoreName());
                history.setNewStaffId(null); // 转入公池，新员工为null
                history.setNewStaffName(null);
                history.setNewStoreId(customer.getStoreId()); // 保持店铺不变
                history.setNewStoreName(customer.getStoreName());
                history.setTransferType("TO_PUBLIC_POOL"); // 新增转移类型
                history.setTransferReason("自动转入公池：超过" + daysThreshold + "天无购买或回访记录");
                history.setOperatorId(1L); // 定时任务操作人设为admin或其他系统用户
                history.setOperatorName("系统"); // 操作人名称
                history.setCreateTime(new Date());
                history.setStatus("0"); // 正常状态

                // 插入客户转移历史
                hmCustomerService.insert(history); // 使用Service层的insert方法

                log.info("客户ID: {} (原服务人员: {}) 已成功转入公池。", customer.getCustomerId(), customer.getStaffName());

            } catch (Exception e) {
                log.error("客户ID: {} 转入公池失败: {}", customer.getCustomerId(), e.getMessage(), e);
                // 可以在这里添加回滚逻辑或重试机制，但目前事务注解已覆盖
            }
        }
        log.info("客户公海（公池）处理任务执行完成。");
    }
}
